package Ms

import (
	"errors"
	"fmt"
	"db2s/ETL"
	"db2s/global"
	"strings"
	"sync/atomic"
)

type TableIndex struct{}

type colAndWhereResult struct {
	selectColumn, asSelectColumn, whereCondition []string
}

func (ms TableIndex) colAndWhere(s global.StartPart) (res colAndWhereResult, err error) {
	var (
		tableSql = TableSql{}
		event    = "[mysqlStartPart]"
	)
	if res.selectColumn, res.asSelectColumn, err = tableSql.SelectColumn(s.SelectColumn); err != nil || len(res.selectColumn) == 0 {
		err = errors.New(fmt.Sprintf("%v get sql select Column fail. Execution process:{chema:%v,table:%v,select column:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.SelectColumn, err))
		return
	}
	if res.whereCondition, err = tableSql.WhereGenerate(s.WhereGenerate); err != nil {
		err = errors.New(fmt.Sprintf("%v get sql select where Condition fail. Execution process:{chema:%v,table:%v,select where Condition:%v,err:%v}", event, s.TableInfo.Schema, s.TableInfo.BackendTableName, s.WhereGenerate, err))
		return
	}
	return
}
func (ms TableIndex) selectCol(selectC []string) (r string) {
	var selectIndexColumn []string
	for _, v := range selectC {
		selectIndexColumn = append(selectIndexColumn, fmt.Sprintf("\"%v\"", v))
	}
	return strings.Join(selectIndexColumn, ",")
}
func (ms TableIndex) orderByNull(s global.StartPart) (r string) {
	if atomic.LoadInt32(s.WhereGenerate.NullBool) == 1 {
		var newIndexColumn []string
		for _, v := range s.WhereGenerate.IndexColumn {
			newIndexColumn = append(newIndexColumn, fmt.Sprintf("CASE WHEN %v IS NULL THEN 0 ELSE 1 END,%v ASC", v, v))
		}
		return fmt.Sprintf("order by %v", strings.Join(newIndexColumn, ","))
	}
	return fmt.Sprintf("order by %v", strings.Join(s.WhereGenerate.IndexColumn, ","))
}
func (ms TableIndex) whereSplicing(whereCondition []string) (r string) {
	if len(whereCondition) > 0 {
		return fmt.Sprintf(" and %v", strings.Join(whereCondition, " and "))
	}
	return ""
}
func hitSpecify(s global.StartPart) (hitIndexName string) {
	if len(s.SelectColumn.IndexName) > 0 && !strings.EqualFold(s.TableInfo.PartitionName, "single") && len(s.TableInfo.PartitionName) > 0 {
		//hitIndexName = fmt.Sprintf(" /*+ index(T %v) */ ", s.SelectColumn.IndexName)
	}
	return
}

// StartPart oracle库下查询表的索引列数据的始末位置，并进行去重排序
func (ms TableIndex) StartPart(s global.StartPart) (result any, err error) {
	var (
		event = "[StartPart]"
		f1    any
		rep   = global.StartPartReturnResult{}
		res   colAndWhereResult
	)
	active := ETL.InstanceActiveS{DBType: DBType, DB: s.DB["single"], StopTime: s.Input.SqlExecStopTime, SqlMode: true}
	if res, err = ms.colAndWhere(s); err != nil {
		return
	}
	rep.BaseResult.Sql = fmt.Sprintf("SELECT %v %v "+
		"FROM %v t where 1 = 1 \n"+
		"%v %v \n"+
		"OFFSET (2 - 1) * %v ROWS FETCH NEXT 1 ROWS ONLY",
		hitSpecify(s), strings.Join(res.selectColumn, ","),
		tableObject(s.TableInfo.Schema, s.TableInfo.BackendTableName, ""),
		ms.whereSplicing(res.whereCondition), ms.orderByNull(s),
		s.Limit.Pagination)
	if rep.BaseResult.TimeOut, f1, err = active.SqlQuery(rep.BaseResult.Sql, ETL.Map); err != nil {
		err = errors.New(fmt.Sprintf("%v sql exec fail. Execution process:{sql:%v,shard:%v,db:%v,err:%v}", event, rep.BaseResult.Sql, "single", s.DB, err))
		return nil, err
	}
	rep.Result = f1.(map[string]any)
	return rep, nil
}
